#include "GridModel.h"
#include <fstream>
#include <sstream>
#include <stdexcept>
#include <cmath>
#include <algorithm>
#include <cctype>
#include <iostream>

// 辅助函数：去除字符串首尾空白字符
static inline std::string trim(const std::string& str) {
    if (str.empty()) {
        return str;
    }
    const std::string whitespace = " \t\r\n";
    const size_t first = str.find_first_not_of(whitespace);
    if (first == std::string::npos) {
        return "";
    }
    const size_t last = str.find_last_not_of(whitespace);
    return str.substr(first, last - first + 1);
}

// 辅助函数：分割字符串
static std::vector<std::string> split(const std::string& s) {
    if (s.empty()) {
        return std::vector<std::string>();
    }
    std::vector<std::string> result;
    std::istringstream iss(s);
    std::string token;
    while (iss >> token) {
        if (!token.empty()) {
            result.push_back(token);
        }
    }
    return result;
}

void GridModel::loadFromFile(const std::string& filename) {
    // 创建日志文件
    std::ofstream logFile("grid_model_log.txt");
    if (!logFile) {
        throw std::runtime_error("无法创建日志文件");
    }

    logFile << "开始加载文件..." << std::endl;

    std::ifstream file(filename);
    if (!file) {
        throw std::runtime_error("无法打开文件: " + filename);
    }

    std::string line;
    std::string currentKeyword;
    bool readingData = false;
    std::vector<double> mapAxesValues;  // 用于收集MAPAXES的值

    while (std::getline(file, line)) {
        // 跳过空行和注释行
        if (line.empty() || line[0] == '#') {
            continue;
        }

        // 去除行尾的空格和制表符
        line = trim(line);
        if (line.empty()) {
            continue;
        }

        // 检查是否是数据结束标记
        if (line[0] == '/' && line.length() == 1) {  // 确保只有单个斜杠才是结束标记
            if (currentKeyword == "MAPAXES" && !mapAxesValues.empty()) {
                // 处理收集到的MAPAXES值
                if (mapAxesValues.size() != 6) {
                    // 如果没有足够的值，使用默认的坐标变换
                    mapAxes.yAxisX = 0.0;
                    mapAxes.yAxisY = 1.0;
                    mapAxes.originX = 0.0;
                    mapAxes.originY = 0.0;
                    mapAxes.xAxisX = 1.0;
                    mapAxes.xAxisY = 0.0;
                    logFile << "使用默认MAPAXES值" << std::endl;
                } else {
                    mapAxes.yAxisX = mapAxesValues[0];
                    mapAxes.yAxisY = mapAxesValues[1];
                    mapAxes.originX = mapAxesValues[2];
                    mapAxes.originY = mapAxesValues[3];
                    mapAxes.xAxisX = mapAxesValues[4];
                    mapAxes.xAxisY = mapAxesValues[5];
                    logFile << "成功读取MAPAXES值" << std::endl;
                }
            }
            readingData = false;
            currentKeyword.clear();
            continue;
        }

        // 检查关键字
        if (line.find("MAPAXES") != std::string::npos) {
            currentKeyword = "MAPAXES";
            readingData = true;
            mapAxesValues.clear();
            logFile << "开始读取MAPAXES数据" << std::endl;
            continue;
        }
        else if (line.find("SPECGRID") != std::string::npos) {
            currentKeyword = "SPECGRID";
            readingData = true;
            logFile << "开始读取SPECGRID数据" << std::endl;
            continue;
        }
        else if (line.find("COORD") != std::string::npos) {
            currentKeyword = "COORD";
            readingData = true;
            size_t coordSize = (gridSize.Nx + 1) * (gridSize.Ny + 1) * 6;
            coordData.reserve(coordSize);
            logFile << "预分配COORD空间: " << coordSize << std::endl;
            continue;
        }
        else if (line.find("ZCORN") != std::string::npos) {
            currentKeyword = "ZCORN";
            readingData = true;
            size_t zcornSize = 8 * gridSize.Nx * gridSize.Ny * gridSize.Nz;
            zcornData.reserve(zcornSize);
            logFile << "预分配ZCORN空间: " << zcornSize << std::endl;
            continue;
        }
        else if (line.find("ACTNUM") != std::string::npos) {
            currentKeyword = "ACTNUM";
            readingData = true;
            size_t actnumSize = gridSize.Nx * gridSize.Ny * gridSize.Nz;
            actnumData.reserve(actnumSize);
            logFile << "预分配ACTNUM空间: " << actnumSize << std::endl;
            continue;
        }

        if (!readingData || currentKeyword.empty()) {
            continue;
        }

        try {
            // 处理数据行
            if (currentKeyword == "MAPAXES") {
                std::istringstream iss(line);
                std::string value;
                while (iss >> value) {
                    if (value == "/") continue;
                    try {
                        mapAxesValues.push_back(std::stod(value));
                    }
                    catch (const std::exception& e) {
                        logFile << "警告: 解析MAPAXES值失败: " << e.what() << ", 值: " << value << std::endl;
                        continue;
                    }
                }
            }
            else if (currentKeyword == "SPECGRID") {
                auto values = split(line);
                if (values.size() >= 3) {
                    gridSize.Nx = std::stoi(values[0]);
                    gridSize.Ny = std::stoi(values[1]);
                    gridSize.Nz = std::stoi(values[2]);
                    logFile << "读取到网格尺寸: " << gridSize.Nx << " x " << gridSize.Ny << " x " << gridSize.Nz << std::endl;
                }
            }
            else if (currentKeyword == "COORD" || currentKeyword == "ZCORN") {
                auto values = split(line);
                if (currentKeyword == "ZCORN") {
                    logFile << "ZCORN行内容: " << line << std::endl;
                    logFile << "分割后的值数量: " << values.size() << std::endl;
                }
                
                for (const auto& value : values) {
                    if (value == "/") {
                        if (currentKeyword == "ZCORN") {
                            logFile << "遇到ZCORN数据结束标记 '/', 当前大小: " << zcornData.size() << std::endl;
                        }
                        continue;
                    }
                    try {
                        if (value.find('*') != std::string::npos) {
                            size_t pos = value.find('*');
                            int count = std::stoi(value.substr(0, pos));
                            double num = std::stod(value.substr(pos + 1));
                            
                            std::vector<double>& target = 
                                (currentKeyword == "COORD") ? coordData : zcornData;

                            // 检查数据大小是否会超出预期
                            size_t expectedSize = (currentKeyword == "COORD") ? 
                                (gridSize.Nx + 1) * (gridSize.Ny + 1) * 6 :
                                8 * gridSize.Nx * gridSize.Ny * gridSize.Nz;
                            
                            if (target.size() + count > expectedSize) {
                                logFile << "警告: " << currentKeyword << "数据可能超出预期大小。当前大小: " 
                                       << target.size() << ", 要添加: " << count 
                                       << ", 预期总大小: " << expectedSize << std::endl;
                            }
                            
                            target.insert(target.end(), count, num);
                            
                            if (currentKeyword == "ZCORN") {
                                logFile << "ZCORN重复数据: " << count << " * " << num 
                                       << " (当前大小: " << target.size() << ")" << std::endl;
                            }
                        }
                        else {
                            double num = std::stod(value);
                            if (currentKeyword == "COORD")
                                coordData.push_back(num);
                            else {
                                zcornData.push_back(num);
                                if (currentKeyword == "ZCORN") {
                                    logFile << "ZCORN单个数据: " << num 
                                           << " (当前大小: " << zcornData.size() << ")" << std::endl;
                                }
                            }

                            // 每处理100个数据点输出一次进度
                            if ((currentKeyword == "ZCORN" && zcornData.size() % 100 == 0) ||
                                (currentKeyword == "COORD" && coordData.size() % 100 == 0)) {
                                logFile << currentKeyword << " 进度: " 
                                       << (currentKeyword == "ZCORN" ? zcornData.size() : coordData.size())
                                       << " / "
                                       << (currentKeyword == "ZCORN" ? 
                                           8 * gridSize.Nx * gridSize.Ny * gridSize.Nz :
                                           (gridSize.Nx + 1) * (gridSize.Ny + 1) * 6)
                                       << std::endl;
                            }
                        }
                    }
                    catch (const std::exception& e) {
                        logFile << "警告: 解析" << currentKeyword << "数据时出错: " << e.what() 
                               << ", 值: " << value 
                               << ", 当前数据大小: " << (currentKeyword == "COORD" ? coordData.size() : zcornData.size())
                               << std::endl;
                        continue;
                    }
                }
                
                if (currentKeyword == "ZCORN") {
                    logFile << "ZCORN行处理完成，当前总大小: " << zcornData.size() << std::endl;
                }
            }
            else if (currentKeyword == "ACTNUM") {
                auto values = split(line);
                for (const auto& value : values) {
                    if (value == "/") continue;
                    try {
                        if (value.find('*') != std::string::npos) {
                            size_t pos = value.find('*');
                            int count = std::stoi(value.substr(0, pos));
                            int num = std::stoi(value.substr(pos + 1));
                            actnumData.insert(actnumData.end(), count, num);
                            
                            logFile << "ACTNUM 重复数据: " << count << " * " << num << std::endl;
                        }
                        else {
                            actnumData.push_back(std::stoi(value));
                        }
                    }
                    catch (const std::exception& e) {
                        logFile << "警告: 解析ACTNUM数据时出错: " << e.what() << ", 值: " << value << std::endl;
                        continue;
                    }
                }
            }
        }
        catch (const std::exception& e) {
            logFile << "错误: 解析" << currentKeyword << "数据时出错: " << e.what() << "\n行内容: " << line << std::endl;
            throw std::runtime_error("解析" + currentKeyword + "数据时出错: " + e.what() + "\n行内容: " + line);
        }
    }

    // 验证数据大小
    size_t expectedCoordSize = (gridSize.Nx + 1) * (gridSize.Ny + 1) * 6;
    size_t expectedZcornSize = 8 * gridSize.Nx * gridSize.Ny * gridSize.Nz;
    size_t expectedActnumSize = gridSize.Nx * gridSize.Ny * gridSize.Nz;

    logFile << "\n数据验证结果：" << std::endl;
    logFile << "网格尺寸: " << gridSize.Nx << " x " << gridSize.Ny << " x " << gridSize.Nz << std::endl;
    logFile << "COORD数据: " << coordData.size() << " / " << expectedCoordSize << std::endl;
    logFile << "ZCORN数据: " << zcornData.size() << " / " << expectedZcornSize << std::endl;
    logFile << "ACTNUM数据: " << actnumData.size() << " / " << expectedActnumSize << std::endl;

    if (coordData.size() != expectedCoordSize) {
        throw std::runtime_error("COORD数据大小不正确: 期望 " + std::to_string(expectedCoordSize) + 
                               ", 实际 " + std::to_string(coordData.size()));
    }
    if (zcornData.size() != expectedZcornSize) {
        throw std::runtime_error("ZCORN数据大小不正确: 期望 " + std::to_string(expectedZcornSize) + 
                               ", 实际 " + std::to_string(zcornData.size()));
    }
    if (actnumData.size() != expectedActnumSize) {
        throw std::runtime_error("ACTNUM数据大小不正确: 期望 " + std::to_string(expectedActnumSize) + 
                               ", 实际 " + std::to_string(actnumData.size()));
    }

    logFile << "文件加载完成" << std::endl;
    logFile.close();
}

std::pair<double, double> GridModel::transformCoordinates(double x, double y) const {
    // 计算坐标系变换矩阵
    double dx = mapAxes.xAxisX - mapAxes.originX;
    double dy = mapAxes.xAxisY - mapAxes.originY;
    double length = std::sqrt(dx * dx + dy * dy);
    
    // 单位向量
    double ex = dx / length;
    double ey = dy / length;
    
    // 计算变换后的坐标
    double deltaX = x - mapAxes.originX;
    double deltaY = y - mapAxes.originY;
    
    // 转换坐标
    double transformedX = deltaX * ex + deltaY * ey;
    double transformedY = -deltaX * ey + deltaY * ex;

    return {transformedX, transformedY};
} 